package com.hliushi.mp.config.id;


import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.hliushi.mp.entity.base.Entity;
import com.hliushi.mp.entity.base.SuperEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * MyBatis Plus 元数据处理类
 * 用于自动 注入 id, createTime, updateTime, createUser, updateUser 等字段
 */
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {

    /**
     * 先默认设置插入用户id为  0
     */
    public static final Long INSERT_USER = 0L;
    /**
     * 先默认设置更新用户id为  2
     */
    public static final Long UPDATE_USER = 2L;

    /**
     * Mail常量
     */
    public static final String MAIL = "mail";
    /**
     * Mail常量默认值
     */
    public static final String MAIL_DEFAULT_VALUE = "hliushi@foxmail.com";

    /**
     * Version常量
     */
    public static final String VERSION = "version";

    /**
     * Version常量默认值
     */
    public static final Integer VERSION_DEFAULT_VALUE = 1;
    /**
     * id类型判断符
     */
    private final static String ID_TYPE = "java.lang.String";
    /**
     * 实体类型判断符
     */
    private final IdGenerate<Long> idGenerator;

    public MyMetaObjectHandler(IdGenerate<Long> idGenerator) {
        super();
        this.idGenerator = idGenerator;
    }

    /**
     * 所有的继承了Entity、SuperEntity的实体，在insert时，
     * id： 会通过IdGenerate生成唯一ID
     * createUser, updateUser: 自动赋予 当前线程上的登录人id
     * createTime, updateTime: 自动赋予 服务器的当前时间
     *
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        boolean flag = true;
        if (metaObject.getOriginalObject() instanceof SuperEntity) {
            Object oldId = ((SuperEntity) metaObject.getOriginalObject()).getId();
            if (oldId != null) {
                flag = false;
            }

            SuperEntity entity = (SuperEntity) metaObject.getOriginalObject();
            if (entity.getCreateTime() == null) {
                this.setFieldValByName(Entity.CREATE_TIME, LocalDateTime.now(), metaObject);
            }
            if (entity.getCreateUser() == null || entity.getCreateUser().equals(0)) {
                // todo 这里原来使用的 BaseContextHandler.getUserId()
                //  获取用户id, 这里获取的信息是从token解析出来的
                //  由于这里没有实现BaseContextHandler, 所有这里先用 两个常量值代替创建用户id和更新用户id
                if (ID_TYPE.equals(metaObject.getGetterType(SuperEntity.CREATE_USER).getName())) {
                    this.setFieldValByName(Entity.CREATE_USER, String.valueOf(INSERT_USER), metaObject);
                } else {
                    this.setFieldValByName(Entity.CREATE_USER, INSERT_USER, metaObject);
                }
            }
        }

        if (flag) {
            Long id = idGenerator.generate();
            if (ID_TYPE.equals(metaObject.getGetterType(SuperEntity.FIELD_ID).getName())) {
                this.setFieldValByName(SuperEntity.FIELD_ID, String.valueOf(id), metaObject);
            } else {
                this.setFieldValByName(SuperEntity.FIELD_ID, id, metaObject);
            }
        }

        if (metaObject.getOriginalObject() instanceof Entity) {
            Entity entity = (Entity) metaObject.getOriginalObject();
            update(metaObject, entity);
        }


        // --------------------------------------------------------------------------
        // 插入数据时填充字段 mail 和 version
        // 先获取到email的值, 再进行判断, 如果为空, 就进行填充
        // 如果不为空, 就不做处理
        log.info("==================== mail start");
        Object mail = this.getFieldValByName(MAIL, metaObject);
        if (Objects.isNull(mail)) {
            /**
             * 注意点: 当这个metaObject对象里面, 没有mail和version的字段信息,
             * this.setFieldValByName(xxx, xx, xx);  等于不执行, 直接返回this对象
             */
            this.setFieldValByName(MAIL, MAIL_DEFAULT_VALUE, metaObject);
        }
        // 添加插入字段时, 默认添加 version = 1
        Object version = this.getFieldValByName(VERSION, metaObject);
        if (Objects.isNull(version)) {
            this.setFieldValByName(VERSION, VERSION_DEFAULT_VALUE, metaObject);
        }
        // --------------------------------------------------------------------------
    }

    private void update(MetaObject metaObject, Entity entity, String et) {
        if (entity.getUpdateUser() == null || entity.getUpdateUser().equals(0)) {
            if (ID_TYPE.equals(metaObject.getGetterType(et + Entity.UPDATE_USER).getName())) {
                this.setFieldValByName(Entity.UPDATE_USER, String.valueOf(UPDATE_USER), metaObject);
            } else {
                this.setFieldValByName(Entity.UPDATE_USER, UPDATE_USER, metaObject);
            }
        }
        if (entity.getUpdateTime() == null) {
            this.setFieldValByName(Entity.UPDATE_TIME, LocalDateTime.now(), metaObject);
        }
    }

    private void update(MetaObject metaObject, Entity entity) {
        update(metaObject, entity, "");
    }

    /**
     * 所有的继承了Entity、SuperEntity的实体，在update时，
     * updateUser: 自动赋予 当前线程上的登录人id
     * updateTime: 自动赋予 服务器的当前时间
     *
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        log.debug("start update fill ....");
        if (metaObject.getOriginalObject() instanceof Entity) {
            Entity entity = (Entity) metaObject.getOriginalObject();
            update(metaObject, entity);
        } else {
            //updateById updateBatchById update(T entity, Wrapper<T> updateWrapper);
            Object et = metaObject.getValue(Constants.ENTITY);
            if (et != null && et instanceof Entity) {
                Entity entity = (Entity) et;
                update(metaObject, entity, Constants.ENTITY + ".");
            }
        }
    }
}
